package io.github.annyylxyms.gyn.gateway.plugin;

import cn.gyn.gynrpc.core.api.LoadBalancer;
import cn.gyn.gynrpc.core.api.RegistryCenter;
import cn.gyn.gynrpc.core.cluster.RoundRibbonLoadBalancer;
import cn.gyn.gynrpc.core.meta.InstanceMeta;
import cn.gyn.gynrpc.core.meta.ServiceMeta;
import io.github.annyylxyms.gyn.gateway.AbstractGatewayPlugin;
import io.github.annyylxyms.gyn.gateway.GatewayPluginChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * direct proxy plugin
 * 判断若路径传了后端的url,直接作为"代理"调后面的路径，否则请求啥样，原封不动返回啥样
 * @date 2024-12-17
 */
@Component("direct")
public class DirectPlugin extends AbstractGatewayPlugin {
    public static final String NAME = "direct";
    private String prefix = GATEWAY_PREFIX + "/" + NAME + "/";
    @Autowired
    RegistryCenter rc;
    LoadBalancer<InstanceMeta> loadBalancer = new RoundRibbonLoadBalancer<>();

    @Override
    public Mono<Void> doHandle(ServerWebExchange exchange, GatewayPluginChain chain) {
        System.out.println("===>>>>> [DirectPlugin] ...");
        String backend = exchange.getRequest().getQueryParams().getFirst("backend");
        Flux<DataBuffer> requestBody = exchange.getRequest().getBody();
        //7、组装响应报文（不能链式操作，一个个加）——提到前面来用于在backend为空时也能返回header内容
        exchange.getResponse().getHeaders().add("Content-Type", "application/json");
        exchange.getResponse().getHeaders().add("gyn.gw.version", "v1.0.0");
        exchange.getResponse().getHeaders().add("gyn.gw.plugin", getName());

        if (backend == null || backend.isEmpty()) {
            return requestBody.flatMap(x -> exchange.getResponse().writeWith(Mono.just(x)))
                    .then(chain.handle(exchange));
        }

        //5、通过webclient发送POST请求
        WebClient client = WebClient.create(backend);
        Mono<ResponseEntity<String>> entity = client.post()
                .header("Content-Type", "application/json")
                .body(requestBody, DataBuffer.class).retrieve().toEntity(String.class);
        //6、通过entity获取响应报文
        Mono<String> body = entity.map(ResponseEntity::getBody);
        return body.flatMap(x -> exchange.getResponse()
                        .writeWith(Mono.just(exchange.getResponse()
                                .bufferFactory().wrap(x.getBytes()))))
                .then(chain.handle(exchange));
    }

    @Override
    public boolean doSupport(ServerWebExchange exchange) {
        return exchange.getRequest().getPath().value().startsWith(prefix);
    }

    @Override
    public String getName() {
        return NAME;
    }
}
